/*!
   \file

   \brief
      This system keeps track of all the entities, keeps lists of them, and creates and destroys
      them.

      ( Note: This class does NOT manage large walking trees. )

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#include "Systems/EntManager/EntManager.hpp"
#include "Entity/Entity.hpp"

EntManager ENTITIES;

bool EntManager::Initialize()
{
   return true;
}

void EntManager::Update( double Elapsed )
{
   numEnabledEntitiesLastUpdate = 0;

   // Delete entities that queued themselves up to be deleted last update
   std::list<uint32_t>::iterator curToDeleteEntHandleIt;
   for ( curToDeleteEntHandleIt = entitiesToDeleteHandles.begin(); curToDeleteEntHandleIt != entitiesToDeleteHandles.end(); ++curToDeleteEntHandleIt )
   {
      uint32_t CurEntityToDeleteHandle = ( *curToDeleteEntHandleIt );

      Entity * CurEntityToDelete = entities.RemoveObject( CurEntityToDeleteHandle );

      delete CurEntityToDelete;
   }
   entitiesToDeleteHandles.clear();

   ObjectStore<Entity>::iterator curEntIt;
   for ( curEntIt = entities.Begin(); curEntIt != entities.End(); ++curEntIt )
   {
      Entity * CurEntity = ( *curEntIt ).second;

      if ( CurEntity->IsEnabled() )
      {
         CurEntity->Update( Elapsed );
         ++numEnabledEntitiesLastUpdate;
      }
   }
}

uint32_t EntManager::AddEntity( Entity * NewEntity )
{
   uint32_t NewHandle = entities.AddObject( NewEntity );

   return NewHandle;
}

void EntManager::DeleteEntity( uint32_t Handle )
{
   // Add it to the deallocation list
   entitiesToDeleteHandles.push_back( Handle );
}

Entity * EntManager::GetEntity( uint32_t Handle )
{
   if ( Handle == kNull32 )
   {
      Warning( "No entity with NULL handle." );
      return NULL;
   }

   return entities[Handle];
}

uint32_t EntManager::GetEnabledEntityCount()
{
   return numEnabledEntitiesLastUpdate;
}

void EntManager::Close()
{
   ObjectStore<Entity>::iterator curEntIt;

   for ( curEntIt = entities.Begin(); curEntIt != entities.End(); ++curEntIt )
   {
      delete ( *curEntIt ).second;
   }
   entities.Clear();
}

EntManager::~EntManager()
{
   this->Close();
}
